package model;
import java.util.Observable;
import java.util.Random;



public class Game2048Model extends Observable implements Model {

	private int[][] game2048;
	private int[] score;
	private final int N=4;
	
	public Game2048Model(){
		game2048 = new int [N][N];
		score = new int[1];
		int count = 0;
		while (count < 2){
			Random rn = new Random();
			int random1 = rn.nextInt(N) + 0;
			int random2 = rn.nextInt(N) + 0;
			if (game2048[random1][random2] == 0){
				game2048[random1][random2] = 2;
				count++;
			}
		}
	}
	
	
	public void moveUp() {
		for (int i=1;i<N;i++){
			for (int j=0;j<N;j++){
				if (game2048[i][j] != 0){
						int temp=i;
						int value=game2048[i][j];
						int flag = 0;
						while (temp>0){
							if (game2048[temp - 1][j] != 0){ 
								flag=1;
								if (game2048[temp - 1][j] == game2048[i][j]){
									flag=2;
									break;
								}
								break;
							}
							temp--;
						}
						if (flag == 0){
							game2048[i][j] = 0;
							game2048[0][j] = value;
						}
						else if (flag == 1) {
							game2048[i][j] = 0;
							game2048[temp][j] = value;
							
						}
						else if (flag == 2) {
							game2048[i][j] = 0;
							game2048[temp-1][j] = value * 2;
							score[0] = score[0] + (value * 2);
						}
					
				}
			}	
		}
		if (checkSpace() == true){
			boolean flag2 = false;
			while (flag2 == false){
				Random rn = new Random();
				int random1 = rn.nextInt(N) + 0;
				int random2 = rn.nextInt(N) + 0;
				if (game2048[random1][random2] == 0){
					game2048[random1][random2] = generateRandom();
					flag2 = true;
				}
			}
		}
		setChanged();
        notifyObservers();	
	}
	
     
	

	public void moveDown() { 
		for (int i=N-2;i>-1;i--){
			for (int j=0;j<N;j++){
				if (game2048[i][j] != 0){
						int temp=i;
						int value=game2048[i][j];
						int flag = 0;
						while (temp<N-1){
							if (game2048[temp + 1][j] != 0){ 
								flag=1;
								if (game2048[temp + 1][j] == game2048[i][j]){
									flag=2;
									break;
								}
								break;
							}
							temp++;
						}
						if (flag == 0){
							game2048[i][j] = 0;
							game2048[N-1][j] = value;
						}
						else if (flag == 1) {
							game2048[i][j] = 0;
							game2048[temp][j] = value;
							
						}    
						else if (flag == 2) {
							game2048[i][j] = 0;
							game2048[temp+1][j] = value * 2;
							score[0] = score[0] + (value * 2);
						}
				}
			}	
		}
		if (checkSpace() == true){
			boolean flag2 = false;
			while (flag2 == false){
				Random rn = new Random();
				int random1 = rn.nextInt(N) + 0;
				int random2 = rn.nextInt(N) + 0;
				if (game2048[random1][random2] == 0){
					game2048[random1][random2] = generateRandom();
					flag2 = true;
				}
			}
		}	
		setChanged();
        notifyObservers();
	}

	public void moveLeft() {
		for (int i=0;i<N;i++){
			for (int j=1;j<N;j++){
				if (game2048[i][j] != 0){
						int temp=j;
						int value=game2048[i][j];
						int flag = 0;
						while (temp>0){
							if (game2048[i][temp - 1] != 0){ 
								flag=1;
								if (game2048[i][temp - 1] == game2048[i][j]){
									flag=2;
									break;
								}
								break;
							}
							temp--;
						}
						if (flag == 0){
							game2048[i][j] = 0;
							game2048[i][0] = value;
						}
						else if (flag == 1) {
							game2048[i][j] = 0;
							game2048[i][temp] = value;
							
						}
						else if (flag == 2) {
							game2048[i][j] = 0;
							game2048[i][temp - 1] = value * 2;
							score[0] = score[0] + (value * 2);
						}
					
				}
			}	
		}
		if (checkSpace() == true){
			boolean flag2 = false;
			while (flag2 == false){
				Random rn = new Random();
				int random1 = rn.nextInt(N) + 0;
				int random2 = rn.nextInt(N) + 0;
				if (game2048[random1][random2] == 0){
					game2048[random1][random2] = generateRandom();
					flag2 = true;
				}
			}
		}		
		setChanged();
        notifyObservers();
	}

	public void moveRight() {
		for (int i=0;i<N;i++){
			for (int j=N-2;j>-1;j--){
				if (game2048[i][j] != 0){
						int temp=j;
						int value=game2048[i][j];
						int flag = 0;
						while (temp<N-1){
							if (game2048[i][temp + 1] != 0){ 
								flag=1;
								if (game2048[i][temp + 1] == game2048[i][j]){
									flag=2;
									break;
								}
								break;
							}
							temp++;
						}
						if (flag == 0){
							game2048[i][j] = 0;
							game2048[i][N-1] = value;
						}
						else if (flag == 1) {
							game2048[i][j] = 0;
							game2048[i][temp] = value;
							
						}
						else if (flag == 2) {
							game2048[i][j] = 0;
							game2048[i][temp + 1] = value * 2;
							score[0] = score[0] + (value * 2);
						}
				}
			}	
		}
		if (checkSpace() == true){
			boolean flag2 = false;
			while (flag2 == false){
				Random rn = new Random();
				int random1 = rn.nextInt(N) + 0;
				int random2 = rn.nextInt(N) + 0;
				if (game2048[random1][random2] == 0){
					game2048[random1][random2] = generateRandom();
					flag2 = true;
				}
			}
		}		
		setChanged();
        notifyObservers();
	}
	
	public int generateRandom() {
		Random rn = new Random();
		int random1 = rn.nextInt(10) + 1;
		if (random1 > 1)
			return 2;
		else return 4;
	}
	

	public int[][] getData() {
		return game2048;
	}
	public int[] getScore() {
		return score;
	}
	
	public boolean checkSpace() {
		int count = 0;
		for (int i=0;i<N;i++){
			for (int j=0;j<N;j++){
				if (game2048[i][j] != 0)
					count++;
			}
		}
		if (count == N*N)
			return false;
		else return true;		
	}

}
